package com.jxb.netty.rocketmqNetty.serializable;

import com.jxb.netty.rocketmqNetty.log.RemotingHelper;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;

import java.nio.ByteBuffer;

/**
 * 通过 LengthFieldBasedFrameDecoder 解决粘包半包
 */
public class RocketDecoder extends LengthFieldBasedFrameDecoder {
    private static final InternalLogger log = InternalLoggerFactory.getLogger(RemotingHelper.ROCKETMQ_REMOTING);

    private static final int FRAME_MAX_LENGTH =
            Integer.parseInt(System.getProperty("com.rocketmq.remoting.frameMaxLength", "16777216"));

    public RocketDecoder() {
        //maxFrameLength：16777216， lengthFieldOffset：0, lengthFieldLength：4, lengthAdjustment：0, initialBytesToStrip：4
        //maxFrameLength：包的最大长度：16777216
        //lengthFieldOffset：长度域的偏移量：0
        //lengthFieldLength：长度域的长度：4
        //lengthAdjustment：长度域中的数据总长度与数据真实大小不一样，所以需要进行调整，可正可负：0
        //initialBytesToStrip：解码过程需要丢失的长度：4
        //————————————————————             ———————————
        //| length   |   数据帧|      ————>|    数据帧   |
        //| 4bytes   |16777216|      ————>|  16777216  |
        //————————————————————             ————————————
        super(FRAME_MAX_LENGTH, 0, 4, 0, 4);
    }

    @Override
    public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = null;
        try {
            frame = (ByteBuf) super.decode(ctx, in);
            if (frame == null) {
                return null;
            }
            //将数据写入到java nio中的ByteBuffer
            ByteBuffer buffer = frame.nioBuffer();
            return RemotingCommand.decode(buffer);
        }catch (Exception e) {
            log.error("decode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e);
            ctx.channel().close();
        }
        return null;
    }
}
